package com.eastdigit.system.service;

import com.eastdigit.system.model.*;
import com.eastdigit.util.Encrypt;
import com.eastdigit.util.StringUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by hehz on 2016/5/30.
 */
@Service
public class PermissionService extends BaseTreeService implements IPermissionService {

    @Autowired
    private MenuService menuService;
    @Autowired
    private IDepartmentService departmentService;
    @Autowired
    private DataScopeService dataScopeService;

    /**
     * 所有菜单和功能点
     * 
     * @return
     */
    @Override
    public List<Menu> queryAllMenuAndFunctions() {
        return menuService.queryAllMenuAndFunctions();
    }

    /**
     * 用户权限
     * 
     * @param userId
     * @return
     */
    @Override
    @Cacheable(value = "authorizationCache", key = "'permission_' + #userId")
    public List<Menu> queryPermissionsOfUser(String userId) {
        return menuService.queryMenuOfUser(userId);
    }

    /**
     * 用户登录时返回的菜单需要验证的功能点
     * 
     * @param userId
     * @return
     */
    @Override
    public JSONObject getUrlPermissionsOfUserForLogin(String userId) {
        List<Menu> menus = queryPermissionsOfUser(userId);
        JSONObject perms = new JSONObject();
        if (menus != null) {
            Map<String, String> map = new HashMap<String, String>();
            for (Menu menu : menus) {
                if (Constants.MENU_TYPE_FUNCTION.equals(menu.getType())) {
                    String codes = map.get(menu.getParentId());
                    map.put(menu.getParentId(),
                            StringUtil.isEmpty(codes) ? menu.getCtrlName() : codes + "," + menu.getCtrlName());
                }
            }
            for (String menuId : map.keySet()) {
                try {
                    perms.put(Encrypt.encodeAES(menuId), map.get(menuId));
                } catch (Exception e) {
                }
            }
        }
        return perms;
    }

    /**
     * 获取用户没有的权限
     * 
     * @param userId
     * @return
     */
    @Override
    public JSONObject queryOutOfAuthedPermissionsOfUser(String userId) {
        JSONObject perms = new JSONObject();
        if (!Constants.SUPER_USER_ID.equals(userId)) {// 不是超级管理员
            Map<String, String> map = new HashMap<String, String>();
            for (Menu menu : queryPermissionsOfUser(userId)) {
                if (Constants.MENU_TYPE_FUNCTION.equals(menu.getType())) {// 1:功能点
                    map.put("M" + menu.getParentId(), null);
                    map.put(menu.getId(), null);
                }
            }
            List<Menu> list = new ArrayList<Menu>();
            for (Menu menu : queryAllMenuAndFunctions()) {
                if (Constants.MENU_TYPE_FUNCTION.equals(menu.getType()) && map.containsKey("M" + menu.getParentId())
                        && !map.containsKey(menu.getId())) {// 1:功能点
                    list.add(menu);
                }
            }
            map.clear();

            for (Menu menu : list) {
                if (Constants.MENU_TYPE_FUNCTION.equals(menu.getType())) {
                    String codes = map.get(menu.getParentId());
                    map.put(menu.getParentId(),
                            StringUtil.isEmpty(codes) ? menu.getCtrlName() : codes + "," + menu.getCtrlName());
                }
            }
            for (String menuId : map.keySet()) {
                try {
                    perms.put(Encrypt.encodeAES(menuId), map.get(menuId));
                } catch (Exception e) {
                }
            }
        }
        return perms;
    }

    /**
     * 验证数据权限
     * 
     * @param userId
     * @param menuId
     * @param url
     * @param deptId
     * @return
     */
    @Override
    public boolean validateUrlPermissionsOfUser(String userId, String menuId, String url, String deptId) {
        if (!Constants.SUPER_USER_ID.equals(userId)) {// 不是超级管理员
            JSONObject jsonObject = dataScopeService.queryUrlDataScopeOfUser(userId);
            // 先判断url，如果没有url，判断菜单
            if (jsonObject.containsKey(url)) {
                String deptIds = jsonObject.getString(url);
                return ("," + deptIds + ",").indexOf("," + deptId + ",") >= 0;
            } else if (jsonObject.containsKey(menuId)) {
                String deptIds = jsonObject.getString(menuId);
                return ("," + deptIds + ",").indexOf("," + deptId + ",") >= 0;
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * 查询用户菜单，不包括功能点
     * 
     * @param userId
     * @return
     */
    @Override
    public JSONArray queryMenuForLeftBarOfUser(String userId) {
        List<Menu> list = queryPermissionsOfUser(userId);
        JSONArray array = new JSONArray();
        for (Menu menu : list) {
            if (Constants.MENU_TYPE_MENU.equals(menu.getType())) {// 0:菜单
                // 菜单的id加密
                JSONObject jsonObject = menu.toJSONObject();
                try {
                    jsonObject.put("menuId", Encrypt.encodeAES(menu.getId()));
                    jsonObject.put("parentMenuId", Encrypt.encodeAES(menu.getParentId()));
                } catch (Exception e) {
                    throw new BusinessException("未知异常，请联系管理员！");
                }
                array.add(jsonObject);
            }
        }
        return BaseTreeService.queryTreeGrid("menuId", "parentMenuId", array);
    }

    /**
     * 获取数据范围
     * 
     * @param userId
     * @param menuId
     * @param parentDeptId
     * @return
     */
    @Override
    public List<IDepartment> getAuthedDepartments(String userId, String menuId, String parentDeptId) {
        List<IDepartment> list = departmentService.queryDescendantDepartmentAndSelf(parentDeptId), departments = new ArrayList<IDepartment>();
        Map<String, String> map = new HashMap<String, String>();
        if (!Constants.SUPER_USER_ID.equals(userId)) {
            for (DataScope scope : dataScopeService.queryMenuDataScopeOfUser(userId, menuId)) {
                map.put(scope.getDeptId(), "");
            }
        }
        for (IDepartment department : list) {
            if (Constants.SUPER_USER_ID.equals(userId) || map.containsKey(department.getDeptId())) {
                departments.add(department);
            }
        }
        return departments;
    }
}
